package de.mrapp.tabswitcher.iterator;

import de.mrapp.tabswitcher.Tab;
import de.mrapp.tabswitcher.model.AbstractItem;
import de.mrapp.tabswitcher.model.Model;
import de.mrapp.tabswitcher.model.TabItem;
import de.mrapp.util.Condition;
import de.mrapp.ohos_util.view.AttachedViewRecycler;

public class ArrayItemIterator extends AbstractItemIterator {

    /**
     * A builder, which allows to configure an create instances of the class {@link
     * ArrayItemIterator}.
     */
    public static class Builder extends AbstractBuilder<Builder, ArrayItemIterator> {

        /**
         * The model, which belongs to the tab switcher, whose items should be iterated by the
         * iterator, which is created by the builder.
         */
        private final Model model;

        /**
         * The view recycler, which allows to inflate the views, which are used to visualize the
         * tabs, which are iterated by the iterator, which is created by the builder.
         */
        private final AttachedViewRecycler<AbstractItem, ?> viewRecycler;

        /**
         * The array, which contains the tabs, which are iterated by the iterator, which is created
         * by the builder.
         */
        private final Tab[] array;

        /**
         * The index of the first tab, which is iterated by the iterator, which is created by the
         * builder.
         */
        private final int firstIndex;

        /**
         * Creates a new builder, which allows to configure and create instances of the class {@link
         * ArrayItemIterator}.
         *
         * @param model        The model, which belongs to the tab switcher, whose items should be iterated by
         *                     the iterator, which is created by the builder, as an instance of the type {@link
         *                     Model}. The model may not be null
         * @param viewRecycler The view recycler, which allows to inflate the views, which are used to visualize
         *                     the tabs, which should be iterated by the iterator, as an instance of the class
         *                     AttachedViewRecycler. The view recycler may not be null
         * @param array        The array, which contains the tabs, which should be iterated by the iterator, as
         *                     an array of the type {@link Tab}. The array may not be null
         * @param firstIndex   The index of the first tab, which should be iterated by the iterator, as an
         *                     {@link Integer} value. The index must be at least 0
         */
        public Builder(final Model model,
                       final AttachedViewRecycler<AbstractItem, ?> viewRecycler,
                       final Tab[] array, final int firstIndex) {
            Condition.INSTANCE.ensureNotNull(model, "The model may not be null");
            Condition.INSTANCE.ensureNotNull(viewRecycler, "The view recycler may not be null");
            Condition.INSTANCE.ensureNotNull(array, "The array may not be null");
            Condition.INSTANCE.ensureAtLeast(firstIndex, 0, "The first index must be at least 0");
            this.model = model;
            this.viewRecycler = viewRecycler;
            if(array==null){
                this.array =null;
            }else{
                this.array = array.clone();
            }

            this.firstIndex = firstIndex;
        }


        @Override
        public ArrayItemIterator create() {
            return new ArrayItemIterator(model, viewRecycler, array, firstIndex, reverse, start);
        }

    }

    /**
     * The model, which belongs to the tab switcher, whose tabs are iterated.
     */
    private final Model model;

    /**
     * The view recycler, which allows to inflate the views, which are used to visualize the
     * iterated tabs.
     */
    private final AttachedViewRecycler<AbstractItem, ?> viewRecycler;

    /**
     * The array, which contains the tabs, which are iterated by the iterator.
     */
    private final Tab[] array;

    /**
     * The index of the first tab, which is iterated by the iterator.
     */
    private final int firstIndex;

    /**
     * Creates a new iterator, which allows to iterate the items, which correspond to the tabs,
     * which are contained by an array.
     *
     * @param model        The model, which belongs to the tab switcher, whose items should be iterated, as an
     *                     instance of the type {@link Model}. The model may not be null
     * @param viewRecycler The view recycler, which allows to inflate the views, which are used to visualize the
     *                     iterated tabs, as an instance of the class AttachedViewRecycler. The view recycler
     *                     may not be null
     * @param array        The array, which contains the tabs, which should be iterated by the iterator, as an
     *                     array of the type {@link Tab}. The array may not be null
     * @param firstIndex   The index of the first tab, which should be iterated by the iterator, as an {@link
     *                     Integer} value. The index must be at least 0
     * @param reverse      True, if the items should be iterated in reverse order, false otherwise
     * @param start        The index of the first item, which should be iterated, as an {@link Integer} value or
     *                     -1, if all items should be iterated
     */
    private ArrayItemIterator(final Model model,
                              final AttachedViewRecycler<AbstractItem, ?> viewRecycler,
                              final Tab[] array, final int firstIndex,
                              final boolean reverse, final int start) {
        Condition.INSTANCE.ensureNotNull(model, "The model may not be null");
        Condition.INSTANCE.ensureNotNull(viewRecycler, "The view recycler may not be null");
        Condition.INSTANCE.ensureNotNull(array, "The array may not be null");
        Condition.INSTANCE.ensureAtLeast(firstIndex, 0, "The first index must be at least 0");
        this.model = model;
        this.viewRecycler = viewRecycler;
        this.array = array;
        this.firstIndex = firstIndex;
        initialize(reverse, start);
    }

    @Override
    public final int getCount() {
        return array.length;
    }


    @Override
    public final AbstractItem getItem(final int index) {
        return TabItem.create(model, viewRecycler, firstIndex + index, array[index]);
    }

}
